package ecomp.uefs.micc.sharedbox.model;

import java.io.*;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.mail.Address;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.swing.DefaultListModel;
import javax.swing.JOptionPane;
import org.apache.commons.mail.EmailException;

/**
 *
 * @author emanuel
 */
public class Client {

    private Socket client;
    private String HOST;
    private int PORT;
    private User user;
    private DefaultListModel model;
    private String dir;
    File afile[];
    private ArrayList emailList;
    public int acknoledge;
    
    public void running(){
        int code;
        boolean answer = true;
        while(answer){
            try {
                DataInputStream input = new DataInputStream(client.getInputStream());
                code = input.readInt();
                System.out.println(code);
                
                switch(code){
                        
                    case 13:
                        setAcknoledge(13);
                        JOptionPane.showMessageDialog(null, "Connected to the FTP Server "
                                                        + getHOST(), "Client Runing", 1);
                        receiveFileList();
                        receiveEmailList();
                        receiveSharedFileList();
                        creatDir();
                        answer = false;
                    break;
            
                    case 14:
                        setAcknoledge(14);
                        JOptionPane.showMessageDialog(null, "Senha Errada "
                                                        , "Client Runing", 1);                 
                        answer = false;
                    break;
                    
                    case 15:
                        setAcknoledge(15);
                        JOptionPane.showMessageDialog(null, "Email não Cadastrado em "
                                                        + getHOST(), "Client Runing", 1);
                        answer = false;                        
                    break;
                        
                    case 30:                        
                        receiveFileList();
                        answer = false;
                    break;
            
                    case 35:
                        
                    break;
            
                    default:
                        System.out.println("Comando não Identificado..");
           
                }
            } catch (IOException ex) {
                Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
            }
        }        
    }
    public void start() throws UnknownHostException, IOException {
        client = new Socket(getHOST(), getPORT());
        
    }

    /**
     *
     */
    public void Login() {
        try {
            
            DataOutputStream output = new DataOutputStream(client.getOutputStream());
            output.writeInt(12);
            ObjectOutputStream oos = new ObjectOutputStream(client.getOutputStream());
            oos.writeObject(getUser());            
            oos.flush();            
           
            // sendFile();
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
        } catch (IOException e) {
            // TODO Auto-generated catch block
        }

    }

    public void stop() {
        try {
            DataOutputStream output = new DataOutputStream(client.getOutputStream());
            output.writeInt(10);
            client.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
        }
    }
    
    /**
     * 
     * @return user
     */

    public User getUser() {
        // TODO Auto-generated method stub
        return user;
    }
    
    /**
     * 
     * @param user 
     */

    public void setUser(User user) {
        this.user = user;
    }
    
    /**
     * 
     */

    public void sendFile(String path) {       
        
        File file = new File(path);
        try {
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
            try {
                DataOutputStream output = new DataOutputStream(client.getOutputStream());
                output.writeInt(22);
                output.writeUTF(getUser().getEmail());
                output.writeLong(file.length());
                output.writeUTF(file.getName());
                System.out.println(file.getName());
                output.flush();
              
                //Cria um buffer  
                byte[] buffer = new byte[4046]; 
                //Envia dados  
                    Integer leitura = null;  
                    do {  
                        leitura = bis.read(buffer, 0, buffer.length);  
                        System.out.flush();  
                        if (leitura != -1) {  
                            output.write(buffer, 0, leitura);  
                        } else {  
                            output.write(leitura);  
                        }  
                        output.flush();  
  
                    } while (leitura != -1);
                    
            } catch (IOException ex) {
                Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
            }
        } catch (FileNotFoundException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
        
    }
    
    /**
     * 
     */
    
    public void download(String file, String owner){
        
        DataInputStream input = null;
        DataOutputStream output = null;
        try {
            input = new DataInputStream(client.getInputStream());
            output = new DataOutputStream(client.getOutputStream());
            
            output.writeInt(25);
            output.writeUTF(file);
            output.writeUTF(owner);

            long size = input.readLong();
       //     String filename = input.readUTF();

            File path = new File(getDir());
            try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(path, file)))) {
                byte[] buffer = new byte[4096];

                //Envia os bytes  
                Integer leitura = null;
                Integer count = 0;
                do {
                    leitura = input.read(buffer, 0, buffer.length);
                    count += leitura;
                    bos.write(buffer, 0, leitura);
                    bos.flush();

                } while (leitura != -1 && count < size);
                bos.close();
                System.out.println("Arquivo Recebido");
                
            }

        } catch (IOException ex) {
            Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * @return the HOST
     */
    public String getHOST() {
        return HOST;
    }

    /**
     * @param HOST the HOST to set
     */
    public void setHOST(String HOST) {
        this.HOST = HOST;
    }

    /**
     * @return the PORT
     */
    public int getPORT() {
        return PORT;
    }

    /**
     * @param PORT the PORT to set
     */
    public void setPORT(int PORT) {
        this.PORT = PORT;
    }
    
    /**
     * Envia Requisição De Registro para o servidor
     * @param user 
     */
    
    public void register(User user) {        
        
        try {
            DataOutputStream output = new DataOutputStream(client.getOutputStream());
            output.writeInt(16);
            ObjectOutputStream oos = new ObjectOutputStream(client.getOutputStream());
            oos.writeObject(user);
            oos.flush();
                int code;
                boolean answer = true;
                    while(answer){
                        try {
                            DataInputStream input = new DataInputStream(client.getInputStream());
                            code = input.readInt();
                         //   System.out.println(code);
                
                                if(code == 17){
                                    System.out.println("Entrou");
                                    JOptionPane.showMessageDialog(null, "Registration Sucessfull "
                                    + getHOST(), "Client Registration", 1);
                                    creatDir();
                                    answer = false;
                                }
            
                                    else if(code == 18){
                                        JOptionPane.showMessageDialog(null, "E-mail Already Exists. Enter a Different E-mail "
                                        , "Client Registration", 1);
                                    answer = false;
                                    }
            
                                        else {
                                            JOptionPane.showMessageDialog(null, "Email não Cadastrado em "
                                            + getHOST(), "Client Runing", 1);
                                            answer = false;
                                        }
                            } catch (IOException ex) {
                                Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
                                }
                        }        
                            } catch (IOException ex) {
                                Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
                                }      
    }
    
    public int receiver(){
        int code = 0;
        try {
            DataInputStream input = new DataInputStream(client.getInputStream());
            code = input.readInt();
        } catch (IOException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        return code;
    }
    
    /**
     * Recebe Lista de arquivos do Servidor
     */    
    
    private void receiveFileList(){      
        try {
            ObjectInputStream input = new ObjectInputStream(client.getInputStream());
            try {
                File afile[] = (File[])input.readObject();
                setList(afile);              
            } catch (ClassNotFoundException ex) {
                Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
            }
        } catch (IOException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
         
    }
    
    private void receiveEmailList(){
        try {
            ObjectInputStream input = new ObjectInputStream(client.getInputStream());
            try {
                ArrayList emailList = (ArrayList)input.readObject();
                setEmailList(emailList);
            } catch (ClassNotFoundException ex) {
                Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
            }
        } catch (IOException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
        
    }
    
    /**
     * Retorna uma lista de arquivos
     * @return afile
     */
    
    public File[] getListFilesServer(){
        
        return afile;
    }
    
    /**
     * 
     * @param list 
     */
    
    public void setList(File[] list){
        this.afile = list;
    }
    
    public void setLog(String msm){
        System.out.println(msm);
    }
    
    public void creatDir(){
            String local = System.getProperty("user.home"); 
            File file = new File(local + System.getProperty("file.separator") +"Sharedbox");
                if(!file.exists()){
                System.out.println("criou");
                file.mkdir();
                }
                    file=new File(file+System.getProperty("file.separator")+getUser().getEmail());
                    if(!file.exists()){
                    file.mkdir();
                    setDir(file.getPath());
                    System.out.println(file);
                    }
                        else{
                        System.out.println("pegou");
                        setDir(file.getPath());
                        }
// System.out.println(file.getPath() + "/" + getUser().getEmail());
     //   System.out.println(file.getPath() + "/" + getUser().getEmail());
    }

    /**
     * @return the dir
     */
    public String getDir() {
        return dir;
    }

    /**
     * @param dir the dir to set
     */
    public void setDir(String dir) {
        this.dir = dir;
    }

    /**
     * @return the emailList
     */
    public ArrayList getEmailList() {
        return emailList;
    }

    /**
     * @param emailList the emailList to set
     */
    public void setEmailList(ArrayList emailList) {
        this.emailList = emailList;
    }
    
    public void sendEmail(ArrayList list, String fileName) throws EmailException {
        
        String recipients = formatRecipients(list);
        Properties props = new Properties();
        props.put("mail.smtp.host", "smtp.gmail.com");
        props.put("mail.smtp.socketFactory.port", "465");
        props.put("mail.smtp.socketFactory.class",
                "javax.net.ssl.SSLSocketFactory");
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.port", "465");

        Session session = Session.getDefaultInstance(props,
                new javax.mail.Authenticator() {
            @SuppressWarnings("deprecation")
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(
                        "sharedboxfiles@gmail.com", "sharedbox2013");
            }
        });

        /**
         * Ativa Debug para sessão
         */
        session.setDebug(true);
        try {

            Message message = new MimeMessage(session);
            message.setFrom(new InternetAddress("sharedboxfiles@gmail.com")); // Remetente

            Address[] toUser = InternetAddress // Destinatário(s)
                    .parse(recipients);

            message.setRecipients(Message.RecipientType.TO, toUser);
            message.setSubject(getUser().getEmail()+" compartilhou um Arquivo com Você");// Assunto
            message.setText(getUser().getEmail()+" compartilhou o arquivo \"" + fileName + "\". Para fazer o download do arquivo acesse "
                    + "sua lista de arquivos compartilhados no Sharedbox!");
            /**
             * Método para enviar a mensagem criada
             */
            Transport.send(message);

            System.out.println("Feito!!!");

        } catch (MessagingException e) {
            throw new RuntimeException(e);
        }

    }
    
    /**
     * Formata a string com os destinatarios do e-mail
     * @param list
     * @return 
     */
    
    public String formatRecipients(ArrayList list){
        String recipients = "";
        for (int i = 0; i < list.size(); i++){
            recipients = recipients.concat(list.get(i).toString() + ",");           
        }       
            
        recipients = recipients.substring(0, recipients.length() - 1);
        
        System.out.println(recipients);
    
        return recipients;
    }
    
    /**
     * Captura o diretorio do arquivo no servidor
     * @param filename
     * @return 
     */
    
    public String getPathFile(String filename){
        String path = null;
        
        for(File file : afile){
                if(file.getName().equals(filename)){
                    path = file.getPath();
                }
        }
       // System.out.println(path);
        return path;       
    }
    
    /**
     * 
     * @param sharedFile 
     */
    
    public void sendSharedFile(SharedFile sharedFile){
        
            DataOutputStream output;
        try {
            output = new DataOutputStream(client.getOutputStream());
            output.writeInt(40);
            ObjectOutputStream oos = new ObjectOutputStream(client.getOutputStream());
            oos.writeObject(sharedFile);
            //oos.flush();
        } catch (IOException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
            
        
    }

    /**
     * @return the acknoledge
     */
    public int getAcknoledge() {
        return acknoledge;
    }

    /**
     * @param acknoledge the acknoledge to set
     */
    public void setAcknoledge(int acknoledge) {
        this.acknoledge = acknoledge;
    }
    
    private void receiveSharedFileList() {
        try {
            ObjectInputStream input = new ObjectInputStream(client.getInputStream());
            getUser().setArquivosCompartilhados((ArrayList) input.readObject());
            
        } catch (IOException | ClassNotFoundException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    
}
